package com.gwtjs.hbm2struts.action.edit;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.StringTokenizer;

/**
 * 生成dao的帮助工具 流操作应该提出来，参数的操作单独在此文件
 * 
 * @author aGuang
 * 
 */
public class Helper {

	private final String ANCHOR = "name";
	private final String QUOTE = "\"";
	private final String SPOT = ".";
	private final String PKG = "struts.action";
	//private final String STAR = "*";
	//private final String SEMI = ";";
	private final String FILE_EXT = "EditorAction.java";
	private final String CLASS_NAME_EXT = "Action";
	private final String SERVICE_EXT = "service";

	// private static int writeCount = 0; //写20次停止刷一下内存用

	private static Helper helper = new Helper();

	private Helper() {
	};

	public static Helper getInstance() {
		return helper;
	}

	/**
	 * 获取.hbm.xml文件转换成字符
	 * 
	 * @param fileName
	 * @return
	 */
	private String getFileData(String fileName) {
		FileReader in = null;
		try {
			File inputFile = new File(fileName);
			in = new FileReader(inputFile);
			char[] fileData = new char[(int) inputFile.length()];
			in.read(fileData);
			return String.copyValueOf(fileData);
		} catch (IOException e) {
			e.printStackTrace();
			return "读文件失败……";
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获取IMPL模板
	 * 
	 * @return
	 */
	private String getTemplateContent() {
		return this.getFileData(Configer.getInstance().getTemplatePath());
	}

	/**
	 * 获取hbm的类全名
	 * 
	 * @param source
	 *            hbm.xml内容
	 * @return
	 */
	private String getHBM(String source) {
		int pos1 = source.indexOf(ANCHOR);
		int pos2 = source.indexOf(QUOTE, pos1);
		int pos3 = source.indexOf(QUOTE, pos2 + 1);

		return source.substring(pos2 + 1, pos3);
	}

	/**
	 * 获取dao的包名
	 * 
	 * @param pkg
	 * @return
	 */
	private String getPackageName(String pkg) {
		String rename = pkg.substring(0,
				pkg.lastIndexOf(SPOT, pkg.lastIndexOf(SPOT) - 1))
				+ SPOT + PKG;
		return rename;
	}

	/**
	 * 取导入的bean
	 * 
	 * @param hbm
	 * @return
	 */
	private String getImportName(String hbm) {
		return hbm.substring(0, hbm.lastIndexOf(SPOT)) ;
	}

	/**
	 * 取类名
	 * 
	 * @param pkg
	 * @return
	 */
	private String getClassName(String pkg) {
		String r = pkg.substring(pkg.lastIndexOf(SPOT) + 1, pkg.length());
		return r;
	}

	/**
	 * 取包的路径 将包转为路径
	 */
	private String getPathName(String pkg) {
		StringBuffer rePkg = new StringBuffer();
		// 用SPOT转换数据
		StringTokenizer token = new StringTokenizer(pkg, SPOT);
		while (token.hasMoreTokens()) {
			rePkg.append(token.nextToken());
			rePkg.append("/");
		}
		return rePkg.toString();
	}

	/**
	 * 取dao文件全路径
	 * 
	 * @param hbm
	 * @return
	 */
	private String getFileAllPath(String hbm) {
		String r = this.getClassName(hbm) + FILE_EXT;
		return r;
	}

	private String getBasePkg(String pkgData){
		String pkg =pkgData.substring(0,pkgData.lastIndexOf(SPOT)); 
		pkg =pkg.substring(0,pkg.lastIndexOf(SPOT)+1);
		return pkg;
	}
	/**
	 * 替换模板的内容
	 * 
	 * @param templateContent
	 * @param pkgData
	 * @param beans
	 * @param className
	 * @return
	 */
	private String doReplace(String templateContent, String pkgData,
			String beans, String className, String daoName,String lowerCaseName) {
		
		Random r=new Random();
		r.setSeed(-8105121279069336025L);
		
		String serialTmp = "#UID#";
		Long serial = r.nextLong();
		
		String pkgTmp = "#PACKAGE#";
		String basePkgTmp = "#BASE_PKG#";
		String impBeanTmp = "#MODEL_PKG#";
		String servicePkgTmp = "#SERVICE_PKG#";
		String classNameTmp = "#CLASSNAME#";
		//String daoNameTmp = "#IMPORTSERVICE#";
		String beanNameTmp = "#LOWER_CASENAME#";
		String basePath = getBasePkg(pkgData);
		String oldDaoPkg = getServicePkg(pkgData);
		templateContent = templateContent.replaceAll(basePkgTmp, basePath);
		templateContent = templateContent.replaceAll(pkgTmp, pkgData);
		templateContent = templateContent.replaceAll(impBeanTmp, beans);
		templateContent = templateContent.replaceAll(classNameTmp, className);
		
		templateContent = templateContent.replaceAll(serialTmp, serial.toString());
		
		templateContent = templateContent.replaceAll(servicePkgTmp, oldDaoPkg);
		templateContent = templateContent.replaceAll(beanNameTmp,lowerCaseName);//将类转换成spring注入的属性名
		return templateContent;
	}
	
	/**
	 * 根据service或model的包取dao包名
	 * 向最后一个目录上级走了两次
	 * @param pkgData
	 * @return
	 */
	private String getServicePkg(String pkgData){
		String tmp = pkgData.substring(0,pkgData.lastIndexOf(SPOT));
		tmp = tmp.substring(0,tmp.lastIndexOf(SPOT));
		tmp = tmp.substring(0,tmp.lastIndexOf(SPOT))+SPOT+SERVICE_EXT;
		return tmp;
	}

	/**
	 * 生成路径
	 * 
	 * @param filePath
	 *            文件路径
	 * @return
	 */
	private boolean mkdir(String filePath) {
		File dir = new File(filePath);
		return dir.mkdirs();
	}

	/**
	 * 写DAOIMPL文件
	 * 
	 * @param filePath
	 *            路径
	 * @param daoFileName
	 * @param fileContent
	 */
	private void bornFile(String filePath, String daoFileName,
			String fileContent) {
		this.mkdir(filePath);
		File outFile = new File(filePath + daoFileName);
		FileWriter out = null;
		try {
			out = new FileWriter(outFile);
			out.write(fileContent.toCharArray());
			// ++writeCount;
		} catch (IOException e) {
			System.out.println("写文件失败……");
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 拼dao名称
	 * @param className
	 * @return
	 */
	private String getServiceImplFileName(String className){
		return className+CLASS_NAME_EXT;
	}
	
	/**
	 * 返回spring bean的名称，就是把第一个字符转成小写
	 * @param className
	 * @return
	 */
	private String getLowerCaseName(String className){
		String end = className.substring(1);
		String start = className.substring(0,className.length()-(className.length()-1));
		System.out.println("NN: "+start.toLowerCase()+end);
		return start.toLowerCase()+end;
	}
	/**
	 * 生成DaoImpl
	 * 
	 * @param templatePath
	 *            模板路径
	 * @param outputPath
	 *            输出路径
	 *            <p>
	 *            这个方法应该重构一下，把参数改成实体的属性，并把此方法上提到CodeGenerator里面
	 *            </p>
	 */
	public void generateAction(String templatePath, String outputPath) {
		String hbmContent = this.getFileData(templatePath); // 取.hbm.xml内容
		String templateContent = this.getTemplateContent(); // 取模板内容
		String pkgAllPath = this.getHBM(hbmContent); // 获取hbm的类全名
		String pkg = this.getPackageName(pkgAllPath); // 获取dao的包名
		String beanPkg = this.getImportName(pkgAllPath); // 取导入的bean名称
		String className = this.getClassName(pkgAllPath); // 取类名,全路径
		
		String lowerCaseName =this.getLowerCaseName(className);
		String actionPkg = pkg+SPOT+lowerCaseName;
		
		String filePath = this.getPathName(actionPkg); // 获取输出全路径
		String daoFileName = this.getFileAllPath(pkgAllPath+SPOT+className);// dao类的名字
		String daoName = this.getServiceImplFileName(className); //根据类名取dao名称
		String daoContent = this.doReplace(templateContent, actionPkg, beanPkg,className,daoName,lowerCaseName);
		this.bornFile(outputPath + "\\" + filePath, daoFileName, daoContent);
	}
}
